linux: Fix xenbus device write function.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 2 Mar 2007 16:26:56 +0000 (16:26 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 2 Mar 2007 16:26:56 +0000 (16:26 +0000)
Signed-off-by: Keir Fraser <keir@xensource.com>
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c

index 6a9eee285f4e79737ab87e1fa1b7225fdf2aa615..f9c1801e1acde9062c916602db3c0c6345e6e62b 100644 (file)
@@ -173,7 +173,7 @@ static ssize_t xenbus_dev_write(struct file *filp,
        void *reply;
        char *path, *token;
        struct watch_adapter *watch, *tmp_watch;
-       int err;
+       int err, rc = len;
 
        if ((len + u->len) > sizeof(u->u.buffer))
                return -EINVAL;
@@ -182,8 +182,9 @@ static ssize_t xenbus_dev_write(struct file *filp,
                return -EFAULT;
 
        u->len += len;
-       if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
-               return len;
+       if ((u->len < sizeof(u->u.msg)) ||
+           (u->len < (sizeof(u->u.msg) + u->u.msg.len)))
+               return rc;
 
        msg_type = u->u.msg.type;
 
@@ -201,14 +202,17 @@ static ssize_t xenbus_dev_write(struct file *filp,
        case XS_SET_PERMS:
                if (msg_type == XS_TRANSACTION_START) {
                        trans = kmalloc(sizeof(*trans), GFP_KERNEL);
-                       if (!trans)
-                               return -ENOMEM;
+                       if (!trans) {
+                               rc = -ENOMEM;
+                               goto out;
+                       }
                }
 
                reply = xenbus_dev_request_and_reply(&u->u.msg);
                if (IS_ERR(reply)) {
                        kfree(trans);
-                       return PTR_ERR(reply);
+                       rc = PTR_ERR(reply);
+                       goto out;
                }
 
                if (msg_type == XS_TRANSACTION_START) {
@@ -231,8 +235,10 @@ static ssize_t xenbus_dev_write(struct file *filp,
        case XS_UNWATCH:
                path = u->u.buffer + sizeof(u->u.msg);
                token = memchr(path, 0, u->u.msg.len);
-               if (token == NULL)
-                       return -EILSEQ;
+               if (token == NULL) {
+                       rc = -EILSEQ;
+                       goto out;
+               }
                token++;
 
                if (msg_type == XS_WATCH) {
@@ -251,7 +257,8 @@ static ssize_t xenbus_dev_write(struct file *filp,
                        err = register_xenbus_watch(&watch->watch);
                        if (err) {
                                free_watch_adapter(watch);
-                               return err;
+                               rc = err;
+                               goto out;
                        }
                        
                        list_add(&watch->list, &u->watches);
@@ -265,7 +272,6 @@ static ssize_t xenbus_dev_write(struct file *filp,
                                                  &u->watches, list) {
                                if (!strcmp(watch->token, token) &&
                                    !strcmp(watch->watch.node, path))
-                                       break;
                                {
                                        unregister_xenbus_watch(&watch->watch);
                                        list_del(&watch->list);
@@ -278,11 +284,13 @@ static ssize_t xenbus_dev_write(struct file *filp,
                break;
 
        default:
-               return -EINVAL;
+               rc = -EINVAL;
+               break;
        }
 
+ out:
        u->len = 0;
-       return len;
+       return rc;
 }
 
 static int xenbus_dev_open(struct inode *inode, struct file *filp)